package com.rlz.base.base

import android.content.Intent
import android.os.Bundle
import android.text.TextUtils
import android.view.View
import androidx.databinding.DataBindingUtil
import androidx.databinding.ViewDataBinding
import androidx.lifecycle.ViewModelProvider
import com.google.gson.JsonSyntaxException
import com.trello.rxlifecycle2.components.support.RxFragmentActivity
import com.rlz.base.R
import com.rlz.base.base.Resource.OnHandleCallback
import com.rlz.base.util.Paging
import com.rlz.base.util.ToastUtils.Companion.showToast
import com.rlz.base.weiget.LoadingDialogFragment
import com.rlz.base.weiget.StateView
import com.rlz.base.weiget.StateView.Flavour
import java.lang.reflect.ParameterizedType
import java.net.ConnectException
import java.net.SocketTimeoutException

/**
 * Created by RLZ
 * on 2021/10/18
 *
 */
abstract class BaseActivity<M : BaseModel, VM : BaseViewModel<M>, DB : ViewDataBinding> :
    RxFragmentActivity() {

    private var mLoadingView: LoadingDialogFragment? = null

    protected lateinit var mViewModel: VM

    protected lateinit var mBinding: DB

    @JvmField
    protected var mBundle: Bundle = Bundle()

    @JvmField
    protected var mActive: Boolean = false

    @JvmField
    protected var mPaging: Paging? = null


    abstract fun logic()

    abstract fun layoutId(): Int

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)

        createBinding()

        createViewModel()

        logic()

        click()
    }

    override fun onPause() {
        super.onPause()
        mActive = false
    }

    override fun onResume() {
        super.onResume()
        mActive = true
    }

    override fun onDestroy() {
        super.onDestroy()
        mBinding.unbind()
    }

    protected open fun click() {

    }

    @Suppress("UNCHECKED_CAST")
    private fun createViewModel() {
        val clazz: Class<VM>
        val type = javaClass.genericSuperclass
        clazz = if (type is ParameterizedType) {
            type.actualTypeArguments[1] as Class<VM>
        } else {
            //如果没有指定参数，则默认使用BaseViewModel
            EmptyViewModel::class.java as Class<VM>
        }

        mViewModel = ViewModelProvider(this).get(clazz)
        mViewModel.setObjectLifecycleTransformer(bindToLifecycle())
    }

    private fun createBinding() {
        mBinding = DataBindingUtil.setContentView(this, layoutId())
        mBinding.lifecycleOwner = this
    }


    protected fun to(clazz: Class<*>) {
        to(clazz, mBundle)
    }

    protected fun to(clazz: Class<*>, b: Bundle) {
        val intent = Intent(this, clazz)
        if (!(b.isEmpty))
            intent.putExtras(b)
        startActivity(intent)
        b.clear()
    }

    abstract inner class OnCallback<T> : OnHandleCallback<T> {

        override fun onLoading(showMessage: String?) {
            show(showMessage)
        }

        override fun onError(error: Throwable?) {
            dismiss()
            if (error is ConnectException) {
                toast(resources.getString(R.string.result_server_error))
                if (mPaging != null) showStateView(StateView.NO_NETWORK)
            } else if (error is SocketTimeoutException) {
                toast(resources.getString(R.string.result_server_timeout))
            } else if (error is JsonSyntaxException) {
                toast(getString(R.string.result_resolve_error))
            } else {
                toast(resources.getString(R.string.result_empty_error))
            }
            if (mPaging != null) showStateView(StateView.ERROR)
        }

        override fun onCompleted() {
            dismiss()
        }

        override fun onFailure(msg: String?) {
            dismiss()
            if (msg != null) {
                toast(msg)
            }
        }
    }

    open fun show(msg: String?) {
        if (mLoadingView == null) mLoadingView = LoadingDialogFragment(msg)
        if (!mLoadingView!!.isVisible)
            if (mPaging != null) {
                if (mPaging!!.curPage == 0) {
                    mLoadingView!!.show(supportFragmentManager, "loading")
                }
            } else {
                mLoadingView!!.show(supportFragmentManager, "loading")
            }
    }

    open fun dismiss() {
        if (mLoadingView != null && mLoadingView!!.isVisible) {
            mLoadingView!!.dismiss()
        }
    }


    protected open fun toast(msg: String) {
        showToast(msg)
    }


    protected open fun showStateView(@Flavour status: Int) {
        showStateView(status, "")
    }

    protected open fun showStateView(@Flavour status: Int, msg: String?) {
        val stateView: StateView = findViewById(R.id.state_view) ?: return
        if (TextUtils.isEmpty(msg)) stateView.setStatus(status) else stateView.setStatus(
            status,
            msg
        )
        stateView.setOnReloadListener { view: View? ->
            retryClick(view)
        }
    }

    protected open fun retryClick(view: View?) {}
}